<?php
/*
 *  This file is part of Urd.
 *
 *  Urd is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *  Urd is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. See the file "COPYING". If it does not
 *  exist, see <http://www.gnu.org/licenses/>.
 *
 * $LastChangedDate: 2008-07-19 14:26:35 +0200 (Sat, 19 Jul 2008) $
 * $Rev: 1309 $
 * $Author: gavinspearhead $
 * $Id: pref_functions.php 1309 2008-07-19 12:26:35Z gavinspearhead $
 */

if (!defined('ORIGINAL_PAGE')) die('This file cannot be accessed directly.');


$pathprf = realpath(dirname(__FILE__));

require_once "$pathprf/../functions/periods.php";
require_once "$pathprf/../functions/defines.php";
require_once "$pathprf/../functions/error_codes.php";
require_once "$pathprf/../functions/functions.php";


function get_user_levels()
{ 
    global $LN;

    $level_array = array(
        CONFIG_LEVEL_BASIC	  => $LN['level_basic'],
        CONFIG_LEVEL_ADVANCED => $LN['level_advanced'],
        CONFIG_LEVEL_MASTER	  => $LN['level_master'] 
    );
    return $level_array;
}


abstract class pref_basic {
	public $level; // config level
	public $name; // name of input
	public $tr_class; // class of of the tr ??
	public $tr_id;    // ID of the tr to use in hiding
	public $javascript; // javascript code to add to the input
	public $text;  // left hand side of text
	public $popup; // text to put in a "hover" --> explanation
	public $error_msg;
    function __construct($lvl, $tx, $nm, $p, $err,  $js=NULL, $tr_i=NULL, $tr_c=NULL){
        assert(is_numeric($lvl));
        $this->level = $lvl;
        $this->text = $tx;
        $this->name = $nm;
		$this->popup = $p;
		if ($err == '' || $err == NULL) 
			$err = ' ';
		$this->error_msg = $err;
		
		$this->javascript = $js;
		$this->tr_id = $tr_i;
		$this->tr_class = $tr_c;
	}
	abstract protected function get_type();
};

class pref_plain extends pref_basic {
	public $value; // value of input 
	function __construct($lvl, $tx, $p, $v, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		parent::__construct($lvl, $tx, '', $p, '',  $js, $tr_i, $tr_c);
		$this->value = $v;

	}
	function get_type() {return 'plain';}
};

// public $select; // selected value

class pref_text extends pref_basic {
	public $size; //size of the text field
	public $value; // value of input 
	function __construct($lvl, $tx, $nm, $p, $err, $v, $sz, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		assert(is_numeric($sz));
		parent::__construct($lvl, $tx, $nm, $p, $err,  $js, $tr_i, $tr_c);
		$this->size = $sz;
		$this->value = $v;
	}
	function get_type() {return 'text';}
};

class pref_password extends pref_basic {
	public $size; //size of the text field
	public $value; // value of input 
	function __construct($lvl, $tx, $nm, $p, $err, $v, $sz, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		assert(is_numeric($sz));
		parent::__construct($lvl, $tx, $nm, $p, $err,  $js, $tr_i, $tr_c);
		$this->size = $sz;
		$this->value = $v;
	}
	function get_type() {return 'password';}
};

class pref_textarea extends pref_basic {
	public $rows; //size of the text field: rows
	public $cols; //size of the text field: rows
	public $value; // value of input 

	function __construct($lvl, $tx, $nm, $p, $err, $v, $rw, $cl, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		assert(is_numeric($rw) && is_numeric($cl));
		parent::__construct($lvl, $tx, $nm, $p, $err, $js, $tr_i, $tr_c);
		$this->rows = $rw;
		$this->cols = $cl;
		$this->value = $v;
	}
	function get_type() {return 'textarea';}
};

class pref_checkbox extends pref_basic {
	public $toggle;
	function __construct($lvl, $tx, $nm, $p, $err, $toggle, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		parent::__construct($lvl, $tx, $nm, $p, $err, $js, $tr_i, $tr_c);
		$this->toggle = $toggle;
	}
	function get_type() {return 'checkbox';}
};

class pref_select extends pref_basic { // todo
	public $options; // the select array
	public $selected; // the selected value
	function __construct($lvl, $tx, $nm, $p, $err, array $options, $selected, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		parent::__construct($lvl, $tx, $nm, $p, $err, $js, $tr_i, $tr_c);
		$this->options = $options;
		$this->selected = $selected;
	}
	function get_type() {return 'select';}
};

class pref_multiselect extends pref_basic {
	public $size; //size of the text field
	public $options_triple; // the select array  of array('name'=>X, 'on'=>Y, 'id'=>Z);
	function __construct($lvl, $tx, $nm, $p, $err, array $options_triple, $sz, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		parent::__construct($lvl, $tx, $nm, $p, $err, $js, $tr_i, $tr_c);
		$this->size = $sz;
		$this->options_triple = $options_triple;
	}
	function get_type() {return 'multiselect';}
};

class pref_period extends pref_basic { // todo
	public $period_name;
	public $period_options;
	public $period_selected;
	public $period_keys;
	public $period_texts;
	public $time1_name;
	public $time1_value;
	public $time2_name;
	public $time2_value;

	function __construct($lvl, $tx, $p, $err, $pn, $ps, $tn1, $tv1, $tn2, $tv2, $en=NULL, $eo=NULL, $es=NULL, $js=NULL, $tr_i=NULL, $tr_c=NULL) {
		parent::__construct($lvl, $tx, NULL, $p, $err, $js, $tr_i, $tr_c);
		global $periods;
		$this->period_name = $pn;
		//$this->period_options = $po;
		list($this->period_keys, $this->period_texts) = $periods->get_periods();
		$this->period_selected = $ps;
		$this->time1_name = $tn1;
		$this->time1_value = $tv1;
		$this->time2_name = $tn2;
		$this->time2_value = $tv2;
		$this->extra_name = $en;
		$this->extra_options = $eo;
		$this->extra_selected = $es;
	}
	function get_type() {return 'period';}
};


function make_error_msg($msg=NULL, $hdr=NULL)
{
	return array('msg'=>$msg, 'hdr'=>$hdr);
}


function verify_email_address($email)
{
	global $LN;
	if (verify_email($email))
		return '';
	else 
		return make_error_msg($LN['error_invalidemail'], $LN['error_error'] . ':'  );
}


function verify_prog($prog, $optional=FALSE)
{
	global $LN;
	if (($optional === TRUE && $prog == '') || is_executable($prog))
		return '';
	else {
		$prog = htmlspecialchars($prog);
		return make_error_msg($LN['error_filenotexec'] . ": <i>'$prog'</i>",  $LN['error_error'] . ':');
	}
}


function verify_numeric_opt($val, $optional=FALSE, $min = NULL, $max = NULL)
{
	global $LN;
	assert(is_bool($optional));
	if ($optional === TRUE && $val == '')
		return '';
	else {
		return verify_numeric($val, $min, $max);
	}
}


function verify_group($group, $optional= FALSE)
{
	global $LN;
	if (($optional === TRUE && $group == '') || posix_getgrnam($group) !== FALSE)
		return '';
	else {
		$group = htmlspecialchars($group);
		return make_error_msg($LN['error_invalidgroup'] . ": <i>'$group'</i>",  $LN['error_error'] . ':');
	}
}


function match_all($haystack, $needles)
{
	$pattern = "/^($needles)+$/";
	
	$rv = preg_match($pattern, $haystack);
	return $rv != 0;
}


function verify_url($text)
{
	global $LN;
	if (validate_url($text)) {
		return '';
	} else {
		if ($text == '') 
			$msg = $LN['error_notleftblank'];
		else
			$msg = $LN['error_invalidvalue'] .  "'<i>$text</i>'<br/> " . $LN['error_urlstart'];
		$text = htmlspecialchars($text);
		return make_error_msg($msg,  $LN['error_error'] . ':' );
	}
}


function verify_text_area($text)
{
	return '';
}


function verify_text($text, $match=NULL)
{
	global $LN;
	if (($match === NULL) && ($text != '')) {
		return '';
	} elseif ($match !== NULL && match_all($text, $match)) {
		return '';
	} else {
		if ($text == '') 
			$msg = $LN['error_notleftblank'];
		else
			$msg = $LN['error_invalidvalue'] . " '<i>$text</i>'";

		$text = htmlspecialchars($text);
		return make_error_msg($msg, $LN['error_error'] . ':');
	}
}


function verify_text_opt($text, $required=TRUE, $match=NULL)
{
	if ($required === FALSE && $text == '')
		return '';
	else 
		return verify_text($text, $match);
}


function verify_dlpath(DatabaseConnection $db, &$_path)
{
	global $LN;
	if (strpos($_path, '..') !== FALSE)
		return make_error_msg($LN['error_invaliddir'] . ": '<i>$path</i>'", $LN['error_error'] . ':' );

	if (substr($_path, -1) != '/')
        $_path .= '/';   

    $path = $_path;

	clearstatcache(); // we want to be sure, so cache values are flushed.

	if (!is_dir($path) || !is_writable($path)) {
		$rv = @mkdir($path, 0775, TRUE);
		set_group($db, $path);
		if ($rv === FALSE) 
			return make_error_msg($LN['error_notmakedir']. " '<i>$path</i>'",  $LN['error_error'] . ':' );
	}
	clearstatcache(); // we want to be sure, so cache values are flushed.
	if ((!is_dir($path) || !is_writable($path)))
		return make_error_msg($LN['error_dirnotwritable'] . " '<i>$path</i>'",  $LN['error_error'] . ':' );

	$rand = 'urd_test_file' . mt_rand(10000,99999);
	$paths = get_all_paths($path);
	foreach($paths as $p){
		if ((!is_dir($p) || !is_writable($p))) {
			$rv = create_dir($p, 0775, TRUE);
			set_group($db, $p);
			if ($rv === FALSE) 
				return make_error_msg($LN['error_notmakedir'] . " '<i>$p</i>'",  $LN['error_error'] . ':' );
			clearstatcache(); // we want to be sure, so cache values are flushed.
			if ((!is_dir($p) || !is_writable($p)))
				return make_error_msg($LN['error_dirnotwritable'] . " '<i>$p</i>'",  $LN['error_error'] . ':' );
			// try creating a file just to be sure
		}
		$rv = touch ($p . $rand);
		if ($rv === FALSE)
			return make_error_msg($LN['error_dirnotwritable'] . " '<i>$p</i>'<br/>" . $LN['error_notestfile'],  $LN['error_error'] . ':' );
		unlink($p . $rand);
	}
	
	return '';
}


function verify_array($val, $arr)
{
	global $LN;
	if (in_array($val, $arr)) 
		return '';
	else {
		return make_error_msg($LN['error_invalidvalue'] , $LN['error_error'] . ':'  );
	}
}


function verify_sort($text, $valids)
{ 
	global $LN;

	if (in_array(strtolower($text), array_map("strtolower",$valids)))
		return '';
	else {
		$text = htmlspecialchars($text);
		return make_error_msg($LN['error_invalidvalue'] . " '<i>$text</i>'",  $LN['error_error'] . ':' );
	}
}


function verify_numeric($val, $min=NULL, $max=NULL)
{
	global $LN;
	if (is_numeric ($val) &&
		(($min === NULL) || ($val >= $min)) &&
		(($max === NULL) || ($val <= $max)))
		return '';
	else {
		$val = htmlspecialchars($val);
		$rv =  $LN['error_invalidvalue'] . " ($val)<br/>";
		if ($min !== NULL)
			$rv .= $LN['error_mustbemore'] . " $min ";
		if ($max !== NULL)
			$rv .= $LN['error_mustbeless'] . " $max ";
		return make_error_msg($rv, $LN['error_error'] . ':' );
	}
}


function clean_area($text)
{
	$text = str_replace('\r', "\r", $text);
	$text = str_replace('\n', "\n", $text);
	$text = str_replace("\r", '', $text);
	$terms = explode("\n", $text);
	$terms_new = array();
	foreach($terms as $line) {
		if ($line != '')
			$terms_new[] = $line;
	}
	$text = implode('\r\n', $terms_new);
	return $text;
}


function set_and_test_pref_text_area ($name, $userID, $clean_area=FALSE)
{
	global $db;
	if (isset($_POST[$name])) {
		$val = $_POST[$name];
		$rv = verify_text_area($val);
		if ($clean_area === TRUE)
			$val = clean_area($val);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';

}


function set_and_test_pref_bool($name, $userID, &$val)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = $_POST[$name];
		set_pref($db, $name, 1, $userID);
		$val = TRUE;
	} else {
		set_pref($db, $name, 0, $userID);
		$val = FALSE;
	}
	return '';
}


function set_and_test_pref_array($name, $userID, $valids)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = $_POST[$name];
		$rv = verify_array($val, $valids);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_sort($name, $userID, $valids)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = $_POST[$name];
		$rv = verify_sort($val, $valids);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_url($name, $userID)
{
	global $db;
	if (isset($_POST[$name])) {
		$val = $_POST[$name];
		$rv = verify_url($val);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_text($name, $userID, $match=NULL, $optional=FALSE, $notrim=FALSE)
{
	global $db;
    if (isset($_POST[$name])) {
		$val = $notrim?($_POST[$name]):(trim($_POST[$name]));
		if ($optional === FALSE) {
			$rv = verify_text($val, $match);
		} else {
			$rv = verify_text_opt($val, !$optional, $match);
		}
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_prog($name, $userID, $optional=NULL)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = trim($_POST[$name]);
		$rv = verify_prog($val, $optional);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_group($name, $userID, $optional=NULL)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = trim($_POST[$name]);
		$rv = verify_group($val, $optional);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_email($name, $userID)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = trim($_POST[$name]);
		$rv = verify_email_address($val);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_dlpath($name, $userID)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = trim($_POST[$name]);
		$rv = verify_dlpath($db, $val);
		if ($rv == '') {
			set_pref($db, $name, $val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function set_and_test_pref_numeric($name, $userID, $min=NULL, $max=NULL)
{
	global $db;

	if (isset($_POST[$name])) {
		$val = trim($_POST[$name]);
		$rv = verify_numeric($val, $min, $max);
		if ($rv == '') {
			set_pref($db, $name, (int)$val, $userID);
			return '';
		} else
			return $rv;
	} else
		return '';
}


function verify_searchbutton($button, $searchbuttons)
{
	global $LN;

	if ($button == '' || in_array($button, array_keys($searchbuttons)))
		return '';
	else
		return make_error_msg($LN['error_invalidbutton']);
}


function set_and_test_pref_buttons($name, $userID, $valids)
{
	global $LN;
	global $db;
	$prefArray = load_prefs_clean($db, $userID);
	$max_buttons = get_pref($db, 'maxbuttons', 0);
	
	if (isset($_POST[$name])) {
		$val = $_POST[$name];
		$i = 1;
		foreach($val as $v) { // first check all for validity
			$rv = verify_searchbutton($v, $valids);
			$i++;
			if ($rv != '') 
				return $rv;
		} 
		if ($i > $max_buttons + 1)
			return make_error_msg($LN['error_toomanybuttons']);
		foreach($prefArray as $k=> $p) { // unset them all first
			if (preg_match('/^button[0-9]+$/', $k))
				set_pref($db, $k, 'none', $userID);
		}
		$i = 1;
		foreach($val as $v){  // set all new ones
			set_pref($db, "button$i", $v, $userID);
			$i++;
		}
		for (; $i<= $max_buttons; $i++)
			set_pref($db, "button$i", 'none', $userID);
		return '';
		
	} else {
		for ($i = 1; $i<= $max_buttons; $i++)
			set_pref($db, "button$i", 'none', $userID);
		return '';
	}
}


function verify_script($db, $path, $name)
{
	global $LN;
    $fn = $path . $name;
	if (preg_match('/^[A-Za-z0-9_\-.+]*$/', $name) != 1) 
		return make_error_msg($LN['error_invalidfilename'] . ': ' . htmlentities($name),  $LN['error_error'] . ':');
	if (!file_exists($fn) || !is_executable($fn))
		return make_error_msg($LN['error_filenotexec'] . ': ' . htmlentities($name),  $LN['error_error'] . ':');
	else 
		return '';
}


function merge_error_msg($error_msg, $new_msg)
{
	if (isset($error_msg['msg'])) {
		if (isset($new_msg['msg']))
			$error_msg['msg'] .= '<br/>' . $new_msg['msg'];
		else 
			;
	} else {
		if (isset($new_msg['msg']))
			$error_msg = $new_msg;
		else
			$error_msg = '';
	}
	return $error_msg;
}


function set_and_test_pref_scripts($path, $name, $userID)
{
	global $db;
	if (isset($_POST[$name])) {
		$rv = '';
		$scripts = '';
		$val = $_POST[$name];
		foreach($val as $v) {
			$rv = merge_error_msg($rv, verify_script($db, $path, $v));
			$scripts .= $v . "\n";
		}
		set_pref($db, $name, $scripts, $userID);
		
		return $rv;
	} else 
		return '';
}

 
?>
